# MadSnake - A snake game
# Copyright (C) 2020-2021  zhiqiang.bzq
#
# See LICENSE. And if you have interest in this project, join us.
#
# zhiqiang.bzq
# bzq23@foxmail.com

from item import *
from common import *
import time

class Result(object):
  def __init__(self, over, message):
    self.over = over
    self.message = message

class Rule(object):
  def __init__(self, gametime):
    self.game_over_time_ = time.time() + gametime

  def LeftTime(self):
    return max(self.game_over_time_ - time.time(), 0)

  def Gaze(self, snakes, ground):
    # check ground.
    for snake in snakes.values():
      head = (snake.Body()[0].x, snake.Body()[0].y)
      if head in ground.ItemMap():
        item = ground.ItemMap()[head]
        if item.Type() == Item.WALL:
          snake.Die()
        elif item.Type() == Item.BODY:
          snake.GrowUp()
        elif not snake.HasBuf(Item.NOBUF):
          snake.AddBuf(item.Type())
        snake.AddScore(item.Score())
        ground.RemoveItem(head)
    # check other snake
    for snake in snakes.values():
      head = (snake.Body()[0].x, snake.Body()[0].y)
      for other_snake in snakes.values():
        if other_snake == snake: continue
        index = 0
        for p in other_snake.Body():
          if head[0] == p.x and head[1] == p.y:
            # crack here, then we check bufs and other info.
            if index == 0:  # head vs. head
              if snake.HasBuf(Item.IRONBUF) and not other_snake.HasBuf(Item.IRONBUF):
                other_snake.Die()
              elif not snake.HasBuf(Item.IRONBUF) and other_snake.HasBuf(Item.IRONBUF):
                snake.Die()
              else:
                snake.Die()
                other_snake.Die()
            elif other_snake.HasBuf(Item.SHIELDBUF):
              snake.Die()
            elif index == other_snake.SevenInch() or other_snake.HasBuf(Item.WEAKDEBUF):
              if other_snake.HasBuf(Item.REVIVEBUF):
                # snake can cut down self and survival if it has REVIVEBUF
                other_snake.Cut(index)
                other_snake.RemoveBuf(Item.REVIVEBUF)
              else:
                # head vs. 7-inch (you know that all snakes have 7-inch without SHILED)
                # head vs. weak snake.
                other_snake.Die()
            else:
              snake.Die()
            break
          index += 1
    # time over.
    if time.time() >= self.game_over_time_:
      maxscore = max([ s.Score() for s in snakes.values() ])
      maxscore_cnt = 0
      for s in snakes.values():
        if s.Score() == maxscore:
          maxscore_cnt += 1
      for s in snakes.values():
        if s.Score() < maxscore or maxscore_cnt != 1:
          s.Die()
    # check is game over.
    alive_cnt = 0
    last_alive_snake = None
    for snake in snakes.values():
      if snake.Alive():
        alive_cnt += 1
        last_alive_snake = snake
    if alive_cnt <= 1:
      # gameover.
      if alive_cnt == 0:
        return Result(True, "DRAW!")
      else:
        return Result(True, "%s WIN!"%(last_alive_snake.Name()))
    return Result(False, "")

